"""
This module contains the interface for building plugins (ConduitPlugin class) and
some builtin plugins.
"""
import re
from string import Template
from django.template import loader, Context
from django.core.mail import send_mail
import django.forms as forms
from django.conf import settings
from instafeed.utils import CustomAsUlFormMixin

class ConduitPlugin:
    """Conduit plugin base class.
    Subclasses must define a key (string) attribute.
    """
    # key: plugin id
    # name: visible name

    allowNew = True # Indicates if new conduits of this type can be added
                    # by the user. If not only auto add conduits it's allowed

    def sendFeed(self, subscription, feed):
        raise NotImplementedError

    @classmethod
    def autoAddConduits(klass, user, currentConduits):
        """If possible add automatically a conduit based on user info.
           The plugin must check the conduit doesn't exists for the user.
           @param currentConduits =Conduit.objects.filter(user=user)
        """
        pass

    @classmethod
    def get_urls(klass):
        return []

# Builtin plugins

class MailConduit(ConduitPlugin):
    """A conduit which sends a mail with the feed."""

    key = "email"
    name = "Email Account"
    defaultTemplate = "titleAndLink.txt"
    template = "conduits/email.html"

    ignoreMailRegexps = [
        re.compile(".*[@]twitteruser[.].*"),
        re.compile(".*[@]facebookuser[.].*"),
        re.compile(".*[@]%s.*[.]com" % settings.SITE_NAME),
        re.compile(".*[@]%s[.]openid[.]com" % settings.SITE_NAME),
        re.compile(".*[@]%s[.]google[.]com" % settings.SITE_NAME),
        re.compile(".*[@]%s[.]yahoo[.]com" % settings.SITE_NAME),
        ]

    def __init__(self, email, mailTemplate=None, subject="New post on $subscriptionName"):
        self.email = email
        self.mailTemplate = mailTemplate or self.defaultTemplate
        self.subject = subject

    def sendFeed(self, subscription, feed):
        t = loader.get_template(self.mailTemplate)
        c = Context({'feed': feed, 'subscription': subscription })
        subject = Template(self.subject).safe_substitute({
            "subscriptionName": subscription.name,
            "feedTitle": feed.title,
            "feedLink": feed.link,
            })
        send_mail(subject, t.render(c), settings.MAIL_FROM,
            [self.email], fail_silently=False)

    @classmethod
    def autoAddConduits(klass, user, currentConduits):
        from instafeed.conduits.models import Conduit
        if not user.email:
            return
        for regex in klass.ignoreMailRegexps:
            if regex.match(user.email):
                return
        name = "Mail to " + user.email
        if not currentConduits.filter(name=name, plugin=klass.key):
            newConduit = Conduit(user=user, name=name, plugin=klass.key,
                params = "{'email': '%s'}" % user.email)
            newConduit.save()

    class Form(CustomAsUlFormMixin, forms.Form):
        email = forms.EmailField()
        subject = forms.CharField(initial = "New post on $subscriptionName",
            help_text="The subject of the mail. You can use the following variables: $subscriptionName, $feedTitle, $feedLink")

    @classmethod
    def update_template_params(klass, request, params):
        if not "email_form" in params:
            params["email_form"] = klass.Form(prefix=klass.key)

    @classmethod
    def validate_new(klass, request):
        form = klass.Form(request.POST)
        if form.is_valid():
            return True, {'email': form.cleaned_data["email"],
                'subject': form.cleaned_data["subject"] }
        else:
            return False, {'email_form': form}
